<template>
  <div class="message" v-if="message">{{ message }}</div>
  <div class="game-container">
    <canvas ref="gomokuCanvas" width="500" height="500"></canvas>
    <div class="controls">
      <el-button type="primary" plain @click="restartGame">🔁 Restart Game</el-button>
      <el-button type="primary" plain @click="undoMove">Undo Move ↩️</el-button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';
import {ElMessage} from "element-plus";

const gomokuCanvas = ref(null);

const gridSize = 20;
const cellSize = 500 / gridSize;
const board = ref(Array.from({ length: gridSize }, () => Array(gridSize).fill(null)));
const currentPlayer = ref('B');
const gameEnded = ref(false);
const history = ref([]);

// 计算游戏结束时的提醒消息
const message = computed(() => {
  if (gameEnded.value) {
    return `${currentPlayer.value === 'B' ? 'Black' : 'White'} is wins!🥳🎉`;
  }
  return '';
});

// 绘制期棋盘网格
const drawBoard = () => {
  const canvas = gomokuCanvas.value;
  const context = canvas.getContext('2d');
  context.clearRect(0, 0, canvas.width, canvas.height);
  for (let i = 0; i <= gridSize; i++) {
    context.beginPath();
    context.moveTo(i * cellSize, 0);
    context.lineTo(i * cellSize, canvas.height);
    context.stroke();
    context.beginPath();
    context.moveTo(0, i * cellSize);
    context.lineTo(canvas.width, i * cellSize);
    context.stroke();
  }
};

// 在指定位置绘制棋子
const drawStone = (x, y, color) => {
  const canvas = gomokuCanvas.value;
  const context = canvas.getContext('2d');
  context.beginPath();
  context.arc(Math.round((x + 0.5) * cellSize), Math.round((y + 0.5) * cellSize), cellSize / 2 - 5, 0, Math.PI * 2);
  context.fillStyle = color;
  context.fill();
  context.strokeStyle = '#404040';
  context.lineWidth =2;
  context.stroke();
};

// 在指定位置落子
const placeStone = (row, col) => {
  if (board.value[row][col] || gameEnded.value) // 该位置已有棋子或游戏结束，则不允许落子
    return ElMessage({
      showClose: true,
      message: '该位置已有棋子, 请重新选择位置!',
      type: 'warning'
    });
  // 记录落子历史
  history.value.push({ row, col, player: currentPlayer.value });
  board.value[row][col] = currentPlayer.value;
  drawStone(col, row, currentPlayer.value === 'B' ? 'black' : 'white');

  if (checkWin(row, col)) {
    gameEnded.value = true;
  } else {
    currentPlayer.value = currentPlayer.value === 'B' ? 'W' : 'B';
  }
};

// 检查当前玩家是否获胜
const checkWin = (row, col) => {
  const directions = [
    { dx: 1, dy: 0 }, // 横向
    { dx: 0, dy: 1 }, // 纵向
    { dx: 1, dy: 1 }, // 斜交 /
    { dx: -1, dy: 1 } // 斜交 \
  ];

  for (const { dx, dy } of directions) {
    let count = 1;

    for (let i = 1; i < 5; i++) {
      const newRow = row + dx * i;
      const newCol = col + dy * i;
      if (
          newRow >= 0 && newRow < gridSize &&
          newCol >= 0 && newCol < gridSize &&
          board.value[newRow][newCol] === currentPlayer.value
      ) {
        count++;
      } else {
        break;
      }
    }

    for (let i = 1; i < 5; i++) {
      const newRow = row - dx * i;
      const newCol = col - dy * i;
      if (
          newRow >= 0 && newRow < gridSize &&
          newCol >= 0 && newCol < gridSize &&
          board.value[newRow][newCol] === currentPlayer.value
      ) {
        count++;
      } else {
        break;
      }
    }

    if (count >= 5) {
      return true;
    }
  }

  return false;
};

// 处理鼠标点击事件
const handleClick = (event) => {
  // 如果游戏已经结束，则不允许落子
  if (gameEnded.value) {
    ElMessage.error('Game has ended!');
    return;
  }
  // 计算点击位置对应的网格坐标
  const rect = gomokuCanvas.value.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;
  // 转换为网格坐标
  const col = Math.floor(x / cellSize);
  const row = Math.floor(y / cellSize);
  // 落子
  placeStone(row, col);
};

// 重新开始游戏
const restartGame = () => {
  board.value = Array.from({ length: gridSize }, () => Array(gridSize).fill(null));
  currentPlayer.value = 'B';
  gameEnded.value = false;
  history.value = [];
  drawBoard();
};

// 撤销上一步落子
const undoMove = () => {
  if (history.value.length === 0 || gameEnded.value) return;
  const lastMove = history.value.pop();
  board.value[lastMove.row][lastMove.col] = null;
  currentPlayer.value = lastMove.player;
  gameEnded.value = false;
  drawBoard();
  redrawHistory();
};

// 重绘历史历史移动的棋子
const redrawHistory = () => {
  history.value.forEach(move => {
    drawStone(move.col, move.row, move.player === 'B' ? 'black' : 'white');
  });
};


// 挂载之后初始化游戏
onMounted(() => {
  drawBoard();
  // 监听鼠标点击事件
  gomokuCanvas.value.addEventListener('click', handleClick);
});
</script>

<style scoped>
.message {
  color: #f5f5f5;
  font-family: "Arial, sans-serif", sans-serif;
  font-size: 32px;
  font-weight: bold;
  white-space: nowrap;
  border-radius: 10px;
  padding: 10px 20px;
  margin-bottom: 20px;
  background-color: #a186be;
  box-shadow: 5px 5px 0 #55acee;
  cursor: pointer;
  transition: transform 0.1s ease-in-out;
}
.game-container {
  text-align: center;

}

canvas {
  background-color: #88ddfa;
  box-shadow: 0 4px 8px rgba(48, 47, 47, 0.2);
  cursor: pointer;
  opacity: 0.8;
}

.controls {
  margin-top: 20px;
}
.el-button {
  padding: 20px;
  font-size: 22px;
  font-weight: bold;
  border-radius: 10px;
  background-color: #a186be;
  color: #f5f5f5;
  box-shadow: 5px 5px 0 #55acee;
  margin: 10px;
  cursor: pointer;
}
</style>